#ifndef _LINUX_DI_DEV_H
#define _LINUX_DI_DEV_H

#include <linux/types.h>
#include "drv_pcie.h"
#include "drv_pcie_irq.h"
#include "drv_cdev.h"

/* IOCTL 命令定义 */
#define IOCTL_DI_MAGIC                  'P'                                 /* 标识设备驱动 */
#define IOCTL_DI_SET_MODE               _IOW(IOCTL_DI_MAGIC, 1, u8)         /* 配置 DI 模式 */
#define IOCTL_DI_SET_EDGE               _IOW(IOCTL_DI_MAGIC, 2, u8)         /* 配置 DI 边沿 */
#define IOCTL_DI_SET_FILTER             _IOW(IOCTL_DI_MAGIC, 3, u16)        /* 配置 DI 滤波时间 */
#define IOCTL_DI_GET_LEVEL              _IOR(IOCTL_DI_MAGIC, 4, u8)         /* 获取 DI 电平 */
#define IOCTL_DI_WAIT_IRQ               _IOR(IOCTL_DI_MAGIC, 5, u8)         /* 等待 DI 中断 */
// #define IOCTL_DI_SET_INIT_LEVEL         _IOW(IOCTL_DI_MAGIC, 9, u32)     /* 配置 DI 初始电平 */
// #define IOCTL_DI_GET_INIT_LEVEL         _IOR(IOCTL_DI_MAGIC, 10, u32)    /* 获取 DI 初始电平 */
// #define IOCTL_DI_START_CAP              _IO(IOCTL_DI_MAGIC,  11)         /* 开始 DI 频率采集 */
// #define IOCTL_DI_GET_CMD                _IOR(IOCTL_DI_MAGIC, 11, u16)    /* 获取 DI 指令 */

#define IOCTL_DI_CHK_MODE               _IOR(IOCTL_DI_MAGIC, 51, u8)        /* 核查 DI 模式 */
#define IOCTL_DI_CHK_EDGE               _IOR(IOCTL_DI_MAGIC, 52, u8)        /* 核查 DI 边沿 */
#define IOCTL_DI_CHK_FILTER             _IOR(IOCTL_DI_MAGIC, 53, u16)       /* 核查 DI 滤波时间 */

#define IOCTL_DI_GET_DRV_VERSION        _IOR(IOCTL_DI_MAGIC, 101, u32)      /* 获取驱动版本号 */
#define IOCTL_DI_GET_FPGA_VERSION       _IOR(IOCTL_DI_MAGIC, 102, u32)      /* 获取 FPGA 版本号 */

// enum di_cmd {
//     DI_CMD_START        = 0x4444,       /* 开始 DI 频率测量指令 */
// };

enum di_mode {
    DI_MOD_LEVEL        = 0,            /* 电平状态检测 */
    // DI_MOD_FREQ         = 1,            /* 测量频率 */
    // DI_MOD_EVENT        = 2,            /* 记录事件 */
    DI_MOD_IRQ          = 3,            /* 中断模式 */
};

enum di_edge {
    /* 硬件为反逻辑，须软件反转边沿寄存器电平 */
    DI_EDGE_RISE        = 1,            /* 上升沿 */
    DI_EDGE_FALL        = 0,            /* 下降沿 */
    DI_EDGE_RISE_FALL   = 2,            /* 上升和下降沿 */
};

/* DI 设备 */
struct di_dev_t {
    void *parent;                       /* 父设备指针 */
    struct device *dev;                 /* 设备描述符 */
    struct mutex lock;                  /* 互斥锁 */
    char name[32];                      /* 设备名 */
    u8 index;                           /* 索引号 */

    u8 mode;                            /* 模式 */
    u8 mode_get;                        /* 模式获取值 */
    u8 edge;                            /* 边沿 */
    u8 edge_get;                        /* 边沿获取值 */
    u16 delay;                          /* 延时时间, us */
    u16 delay_get;                      /* 延时时间获取值 */
    u32 level;                          /* 电平 */
    bool cap_edge;                      /* 捕获边沿 */
    wait_queue_head_t edge_wq;          /* 边沿 等待队列 */
};

/* DI 控制器 */
struct di_ctrl_t {
    struct device *dev;                                                 /* 设备描述符 */
    struct mutex lock;                                                  /* 互斥锁 */
    char name[32];                                                      /* 设备名称 */
    u8 num;                                                             /* 设备数量 */

    struct pcie_dev_t *pcie_dev;                                        /* PCIe 设备指针 */
    u32 (*read_reg)(struct pcie_dev_t *pcie_dev, u32 reg);              /* 读寄存器 */
    void (*write_reg)(struct pcie_dev_t *pcie_dev, u32 reg, u32 val);   /* 写寄存器 */
    struct cdev_ctrl_t cdev_ctrl;                                       /* 字符设备控制器 */
    struct pcie_irq_ctrl_t irq_ctrl;                                    /* 中断控制器 */
    struct di_dev_t *di;                                                /* DI */

    u32 init_level;                                                     /* DI 初始电平 */
    u32 init_level_get;                                                 /* DI 初始电平获取值 */
    u32 level;                                                          /* DI 当前电平 */

    u32 drv_ver;                                                        /* 驱动版本号 */
    u32 fpga_ver;                                                       /* FPGA 版本号 */
};

/* 初始化 DI 控制器 */
int init_di_ctrl(struct pcie_dev_t *pcie_dev, struct cdev_dev_t *cdev_dev, 
                 struct di_ctrl_t *pctrl, struct di_dev_t *di, 
                 const char *ctrl_name, u8 dev_num);
/* 注销 DI 控制器 */
void exit_di_ctrl(struct di_ctrl_t *ctrl, u8 dev_num);

#endif /* _LINUX_DI_DEV_H */
